package stv5;

import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * Wraps the HTTP response to a client
 * 
 * @author dhleong
 *
 */
public class Response {

	private static SimpleDateFormat dateFormatter 
		= new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
	
	static {
		// make sure it's in GMT
		dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
	}
	
	private String contentType = null, status = "";
	private StringBuffer stringBody = null;
	private byte[] byteBody = null;
	
	public Response() {
		stringBody = new StringBuffer();
	}
	
	/**
	 * Alias for {@link #addBody(String)}
	 * @param addition
	 */
	public void append(String addition) {
		addBody(addition);
	}
	
	/**
	 * Add some text to the body of this response
	 * 
	 * @param addition
	 */
	public void addBody(String addition) {
		if (stringBody == null)
			stringBody = new StringBuffer(addition);
		else stringBody.append(addition);
	}
	
	/**
	 * This is a dumb process and doesn't consult
	 * 	{@link #isText()} to see if it is wise to use
	 * 	this or not
	 * 
	 * @return
	 */
	public byte[] getBytes() {
		return byteBody;
	}
	
	/**
	 * @return How big the body is, regardless of how it was created
	 */
	public int getLength() {
		if (isText()) {
			// silliness? Oh well. If we're calling this, then
			//  we shouldn't be making any more changes...
			byteBody = stringBody.toString().getBytes(); 
		} 
		return byteBody.length;
	}	
	
	/**
	 * @return True if the body was created {@link #addBody(String)}
	 * 	or {@link #append(String)} or {@link #setBody(String)},
	 * 	and can be sent using something that writes straight text,
	 * 	like PrintWriter
	 */
	public boolean isText() {
		return byteBody == null;
	}
	
	public void setBody(String body) {
		stringBody = new StringBuffer(body);
	}
	
	public void setBody(byte[] data) {
		byteBody = data;
	}
	
	/**
	 * EG: "200 OK" or "404 Not Found"
	 * 
	 * @param status
	 */
	public void setStatus(String status) {
		this.status = status;
	}
	
	/**
	 * EG: "text/html", "text/css", "image/png" 
	 * @param type
	 */
	public void setContentType(String type) {
		contentType = type;
	}
	
	/**
	 * This is a dumb process, and doesn't check if
	 * 	{@link #isText()} or not. Just so you know
	 *  
	 * @param output
	 */
	public void writeBody(PrintWriter output) {
		output.append( stringBody );
	}
	
	/**
	 * Dump the header informations into the PrintWriter
	 * 
	 * @param output
	 */
	public void writeHeaders(PrintWriter output) {
		output.write("HTTP/1.0 "+status+"\r\n");
		output.write("Date: " + dateFormatter.format(new Date()) + "\r\n");
		
		if (contentType != null && contentType.indexOf("image") == -1) {
			// make sure foolish browsers (*caugh*PS3*caugh*) don't cache
			//  stuff and end up displaying the wrong things
			// caching images is okay though
			output.append("Cache-Control: no-cache\r\n");
			output.append("Expires: " + dateFormatter.format(new Date()) + "\r\n");
		}
		
		// the PS3 browser is retarded and needs Content-Type, but
		//  I don't have any great way to serve it correctly right now,
		//  so this is a bit of a hack...		
		if (contentType != null)
			output.append("Content-type: " + contentType + "\r\n");
		
		output.append("Content-length: " + getLength() + "\r\n");
		output.append("\r\n");				
	}
}
